package com.dingreading.cloud.mall.config;

import com.aliyuncs.exceptions.ClientException;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.DescribeException;
import com.google.gson.JsonSyntaxException;
import org.apache.http.HttpException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.List;

/**
 * 统一异常处理
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    public static final Logger logger = LogManager.getLogger(GlobalExceptionHandler.class);

    /**
     * Vaild校验错误捕获处理
     */
    @ExceptionHandler(BindException.class)
    public R<Object> validationBodyException(BindException e) {
        logger.error("validationBodyException系统异常", e);

        BindingResult result = e.getBindingResult();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            if (!errors.isEmpty()) {
                FieldError fieldError = (FieldError) errors.get(0);
                return R.fail(500, fieldError.getDefaultMessage());
            }
        }
        return R.ok();
    }

    /**
     * 判断错误是否是已定义的已知错误，不是则由未知错误代替，同时记录在log中
     */
    @ExceptionHandler(value = Exception.class)
    public R<Object> exceptionGet(Exception e) {
        logger.error("捕获系统异常", e);
        if (e instanceof DescribeException) {
            DescribeException exception = (DescribeException) e;
            return R.fail(exception.getStatusCode(), exception.getMessage());
        } else if (e instanceof SocketException) {
            return R.fail(500, "无网络连接");
        } else if (e instanceof SocketTimeoutException) {
            return R.fail(500, "请求超时");
        } else if (e instanceof HttpException) {
            return R.fail(500, "http错误");
        } else if (e instanceof NullPointerException) {
            e.printStackTrace();
            return R.fail(500, "空指针异常");
        } else if (e instanceof JsonSyntaxException) {
            return R.fail(500, "Json数据解析异常");
        } else if (e instanceof ArrayIndexOutOfBoundsException) {
            return R.fail(500, "数组下标越界");
        } else if (e instanceof ClassCastException) {
            return R.fail(500, "数据类型转换错误");
        } else if (e instanceof ClientException) {
            return R.fail(500, "人脸识别失败");
        } else if (e instanceof ArithmeticException) {
            return R.fail(500, "算术运算异常");
        }/* else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException exception = (ConstraintViolationException) e;
            Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();
            List<String> list = new ArrayList<>();
            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                String messageTemplate = constraintViolation.getMessageTemplate();
                list.add(messageTemplate);
            }
            String message = list.stream().collect(Collectors.joining(","));
            return R.fail(500, message);
        }*/ else {
            return R.fail(500, "系统错误");
        }
    }

    /**
     * 不进入controller层的异常捕获
     */
    @ExceptionHandler({MethodArgumentTypeMismatchException.class, MissingServletRequestParameterException.class, IllegalArgumentException.class})
    public R<Object> mismatchErrorHandler(Exception e) {
        logger.error("mismatchErrorHandler系统异常", e);

        String message = "";
        if (e instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException exception = (MethodArgumentTypeMismatchException) e;
//            MethodParameter parameter = exception.getParameter();
//            errmsg = "参数转换失败，方法："+ Objects.requireNonNull(exception.getParameter().getMethod()).getName()
//                    +",期望参数类型："+exception.getParameter().getParameterType()
//                    +",参数："+exception.getName()
//                    +",信息："+exception.getMessage();
            message = "参数类型转换异常";
        } else if (e instanceof MissingServletRequestParameterException) {
            message = "参数信息异常";
        } else if (e instanceof IllegalArgumentException) {
            message = "不合法的参数异常";
        } else {
            message = "未知错误";
        }
        return R.fail(400, message);
    }

}
